package com.yonyou.pmclouds.team.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoInsertProcessor;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoUpdateProcessor;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.ConcurrentOperationException;
import com.yonyou.pmclouds.basecom.lock.AutoReleaseLockUtil;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.project.entity.ProjectConst;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.team.rmiitf.TeamEnterpriseQuery;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseVO;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.mapper.TeamEnterpriseMapper;
import com.yonyou.pmclouds.team.mapper.TeamMapper;
import com.yonyou.pmclouds.team.processor.TeamInsertValidProcessor;
import com.yonyou.pmclouds.team.processor.TeamMemberDeleteCheck;
import com.yonyou.pmclouds.team.rmiitf.TeamMemberMaintain;
import com.yonyou.pmclouds.team.rmiitf.TeamMemberQuery;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = TeamMemberMaintain.class)
public class TeamMemberMaintainImpl implements TeamMemberMaintain {

    @Autowired
    private TeamMapper mapper;
    @Autowired
    private TeamEnterpriseMapper entMapper;
    @Autowired
    private ProjectSimpleQuery projectSimpleQuery;
    @Autowired
    private TeamMemberQuery teamMemberQuery;
    @Autowired
    private TeamEnterpriseQuery teamEnterpriseQuery;

    @Override
    public String[] addMembersToProject(String projectid, TeamMemberVO[] mems) throws BusinessException {
        if (ArrayUtils.isEmpty(mems)) {
            return null;
        }
        // lock project
        if (!AutoReleaseLockUtil.addAutoReleaseLock(projectid)) {
            throw new ConcurrentOperationException();
        }
//        ProjectVO project = projectSimpleQuery.queryProject(projectid);
//        if (project.getProjectState() == ProjectConst.STATE_END) {
//            throw new BusinessException("已经结束的项目，不可再操作项目团队！");
//        }
        // 去除不需要在加入团队的用户
        Set<String> members = new HashSet<String>();
        for (int i = 0; i < mems.length; i++) {
            mems[i].setPkProject(projectid);
            mems[i].setPkTenant(RuntimeEnvironment.getTenantId());
            if (!members.add(mems[i].getPkUser())) {
                throw new BusinessException("项目团队中存在重复人员");
            }
        }

        String[] existMembers = teamMemberQuery.queryExistMember(projectid, members.toArray(new String[members.size()]));

        if (ArrayUtils.isNotEmpty(existMembers))
            throw new BusinessException("项目团队中存在重复人员");

        SingleInsertBpTemplate<TeamMemberVO> template = new SingleInsertBpTemplate<>(mapper);
        // 新增前校验
        template.addBeforeProcessor(new TeamInsertValidProcessor(projectSimpleQuery, projectid));
        // 设置审计信息
        template.addBeforeProcessor(new AuditInfoInsertProcessor<TeamMemberVO>());
        for (TeamMemberVO memberVO : mems) {
            template.insert(memberVO);
        }
        String[] pks = new String[mems.length];
        for (int i = 0; i < mems.length; i++) {
            pks[i] = mems[i].getPkTeamMember();
        }
        return pks;
    }

    @Override
    public String removeFromTeam(String pkTeamMember, String changeFlag) throws BusinessException {
        // 是否校验当前用户是否是项目的项目经理
        TeamMemberVO memberVO = new TeamMemberVO();
        memberVO.setPkTeamMember(pkTeamMember);
        memberVO.setChangeFlag(changeFlag);
        SingleDeleteBpTemplate<TeamMemberVO> bp = new SingleDeleteBpTemplate<>(mapper);
//        bp.addBeforeProcessor(new TeamMemberDeleteCheck(projectSimpleQuery));
        bp.delete(memberVO);
        return memberVO.getPkTeamMember();
    }

    @Override
    public TeamMemberVO[] addMembers(TeamMemberVO[] memberVOs) throws BusinessException {

        if (ArrayUtils.isEmpty(memberVOs)) {
            return null;
        }
        // 所有的用户主键
        List<String> pkUserList = new ArrayList<String>();
        // 所有的项目主键
        List<String> pkProjectList = new ArrayList<String>();
        // 用户主键+项目主键 与 项目团队成员的对应关系
        Map<String, TeamMemberVO> userProToMemberMap = new HashMap<String, TeamMemberVO>();
        for (TeamMemberVO member : memberVOs) {
            pkUserList.add(member.getPkUser());
            pkProjectList.add(member.getPkProject());
            userProToMemberMap.put(member.getPkUser() + member.getPkProject(), member);
        }
        // 去除掉已经在项目团队中存在的项目成员，得到真正需要新增的项目团队成员
        TeamMemberVO[] newTeamMemberVOs = removeExistsMembers(userProToMemberMap, pkUserList);

        if (ArrayUtils.isEmpty(newTeamMemberVOs))
            return null;

        Map<String, ProjectVO> pkProMap = projectSimpleQuery.queryProjects(pkProjectList.toArray(new String[0]));

        SingleInsertBpTemplate<TeamMemberVO> template = new SingleInsertBpTemplate<>(mapper);
        Byte projectState = null;
        for (TeamMemberVO memberVO : newTeamMemberVOs) {
            // 新增前补充项目状态
            fillMemberProState(memberVO, pkProMap);
            // 设置审计信息
            template.addBeforeProcessor(new AuditInfoInsertProcessor<TeamMemberVO>());
            template.insert(memberVO);
        }

        return memberVOs;
    }

    /**
     * 去除掉已经在项目团队中存在的项目成员，得到真正需要新增的项目团队成员
     *
     * @param userProToMemberMap
     * @param pkUserList
     * @return
     */
    private TeamMemberVO[] removeExistsMembers(Map<String, TeamMemberVO> userProToMemberMap, List<String> pkUserList) {
        TeamMemberVO[] existMemberVOs = mapper.queryByPkUsers(pkUserList.toArray(new String[0]));

        for (TeamMemberVO memberVO : existMemberVOs) {
            if (userProToMemberMap.get(memberVO.getPkUser() + memberVO.getPkProject()) != null)
                userProToMemberMap.remove(memberVO.getPkUser() + memberVO.getPkProject());
        }

        return userProToMemberMap.values().toArray(new TeamMemberVO[0]);
    }

    private void fillMemberProState(TeamMemberVO memberVO, Map<String, ProjectVO> pkProMap) {
        if (pkProMap.get(memberVO.getPkProject()) != null)
            memberVO.setProjectState(pkProMap.get(memberVO.getPkProject()).getProjectState());
    }

    @Override
    public void updateTeamMemberForProject(String pkProject, TeamMemberVO[] updateMemberVOs, TeamMemberVO[] insertMemberVOs, TeamMemberVO[] deleteMemberVOs, TeamEnterpriseVO[] insertEnterpriseVOs, TeamEnterpriseVO[] updateEnterpriseVOs) throws BusinessException {

        if (ArrayUtils.isNotEmpty(deleteMemberVOs)) {
            for (TeamMemberVO teamMemberVO :
                    deleteMemberVOs) {
                this.removeFromTeam(teamMemberVO.getPkTeamMember(), teamMemberVO.getChangeFlag());
            }
        }

        // 更新成员信息，目前使用到的更新场景是切换项目经理后，原项目经理不删除，更新角色
        // 现有项目经理已经在企业团队中存在时，将角色更改为0，及项目经理角色
        if (ArrayUtils.isNotEmpty(updateMemberVOs)) {
            String[] updateFields = new String[]{CommonFieldConst.MODIFIER, CommonFieldConst.MODIFYTIME, TeamMemberVO.USER_ROLE};
            SingleUpdateBpTemplate<TeamMemberVO> updateBpTemplate = new SingleUpdateBpTemplate<>(mapper, updateFields);
            updateBpTemplate.addBeforeProcessor(new AuditInfoUpdateProcessor<TeamMemberVO>());
            for (TeamMemberVO teamMemberVO : updateMemberVOs) {
                updateBpTemplate.update(teamMemberVO);
            }
        }
        ProjectVO projectVO = null;
        if (ArrayUtils.isNotEmpty(insertMemberVOs)) {
            TeamMemberVO[] newEntRoleMember = null;
            TeamMemberVO[] oldEntRoleMember = null;
            Map<String, Byte> entRuleMap = new HashMap<>();

            getEntRuleMap(entRuleMap, insertEnterpriseVOs, updateEnterpriseVOs);

            projectVO = projectSimpleQuery.queryProject(pkProject);

            if (!entRuleMap.isEmpty()) {
                for (TeamMemberVO memberVO : insertMemberVOs) {
                    if (entRuleMap.get(memberVO.getPkEnterprise()) != null) {
                        if (projectVO != null && StringUtils.isNotEmpty(projectVO.getManager()) && projectVO.getManager().equalsIgnoreCase(memberVO.getPkUser())) {
                            memberVO.setUserRole(TeamMemberVO.UserRoleConst.ROLE_MANAGER);
                        } else if (memberVO.getUserRole() != TeamMemberVO.UserRoleConst.ROLE_MANAGER) {
                            memberVO.setUserRole(entRuleMap.get(memberVO.getPkEnterprise()));
                        }
                        newEntRoleMember = ArrayUtils.add(newEntRoleMember, memberVO);
                    } else {
                        oldEntRoleMember = ArrayUtils.add(oldEntRoleMember, memberVO);
                    }
                }
            } else {
                oldEntRoleMember = insertMemberVOs;
            }

            if (ArrayUtils.isNotEmpty(oldEntRoleMember)) {
                fillEntRule(pkProject, oldEntRoleMember);
            }

            this.addMembersToProject(pkProject, ArrayUtils.addAll(newEntRoleMember, oldEntRoleMember));
        }

    }

    private void getEntRuleMap(Map<String, Byte> entRuleMap, TeamEnterpriseVO[] insertEnterpriseVOs, TeamEnterpriseVO[] updateEnterpriseVOs) {

        if (ArrayUtils.isNotEmpty(insertEnterpriseVOs)) {
            for (TeamEnterpriseVO enterpriseVO : insertEnterpriseVOs) {
                entRuleMap.put(enterpriseVO.getPkEnterprise(), enterpriseVO.getEntRole());
            }
        }

        if (ArrayUtils.isNotEmpty(updateEnterpriseVOs)) {
            for (TeamEnterpriseVO enterpriseVO : updateEnterpriseVOs) {
                entRuleMap.put(enterpriseVO.getPkEnterprise(), enterpriseVO.getEntRole());
            }
        }

    }

    private void fillEntRule(String pkProject, TeamMemberVO[] oldEntRoleMember) throws BusinessException {
        String[] pkEnts = new String[0];
        Map<String, Byte> oldEntRole = new HashMap<>();
        for (TeamMemberVO memberVO : oldEntRoleMember) {
            pkEnts = ArrayUtils.add(pkEnts, memberVO.getPkEnterprise());
        }

        TeamEnterpriseVO[] enterpriseVOS = teamEnterpriseQuery.queryByPkEnts(pkEnts);
        for (TeamEnterpriseVO enterpriseVO : enterpriseVOS) {
            if (pkProject.equals(enterpriseVO.getPkProject())) {
                oldEntRole.put(enterpriseVO.getPkEnterprise(), enterpriseVO.getEntRole());
            }
        }
        if (!oldEntRole.isEmpty()) {
            for (TeamMemberVO memberVO : oldEntRoleMember) {
                if (memberVO.getUserRole() != TeamMemberVO.UserRoleConst.ROLE_MANAGER) {
                    memberVO.setUserRole(oldEntRole.get(memberVO.getPkEnterprise()));
                }
            }
        }
    }
}
